﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.IO;
using ECMCommMan;
using CSVFileHandler;

namespace ECMSim
{
    public partial class FormMain : Form, IECMCommMan
    {
        #region Manager Enums
        /// <summary>
        /// enumeration to hold our transmission types
        /// </summary>
        public enum TransmissionType { Text, Hex, ECM, DASH }

        protected Color[] MessageColor = { Color.Blue, Color.Green, Color.Black, Color.Orange, Color.Red };

        //public enum ECMCommandType : byte
        //{
        //    ECMGet = 0x52,
        //    ECMSet = 0x57,
        //    ECMVersion = 0x56,
        //    ECMRunTimeData = 0x43
        //};


        #endregion

        ECMCommunicationManager ecmCommMan;
        string transType = string.Empty;

        public FormMain()
        {
            InitializeComponent();
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            ecmCommMan = new ECMCommunicationManager(this); 
            LoadValues();
            SetDefaults();
            SetControlState();
            this.Height = 640;
            this.Width = 895;
            gbDashRequest.Location = new System.Drawing.Point(gbGauges.Location.X, gbGauges.Location.Y);
        }

        private void cmdOpen_Click(object sender, EventArgs e)
        {
            ecmCommMan.Parity = cboParity.Text;
            ecmCommMan.StopBits = cboStop.Text;
            ecmCommMan.DataBits = cboData.Text;
            ecmCommMan.BaudRate = cboBaud.Text;
            ecmCommMan.PortName = cboPort.Text;
            ecmCommMan.OpenPort();

            btnCmdOpen.Enabled = false;
            btnCmdClose.Enabled = true;
            btnCmdSend.Enabled = true;
        }

        /// <summary>
        /// Method to initialize serial port
        /// values to standard defaults
        /// </summary>
        private void SetDefaults()
        {
            cboPort.SelectedIndex = 0;
            cboBaud.SelectedText = "9600";
            cboParity.SelectedIndex = 0;
            cboStop.SelectedIndex = 1;
            cboData.SelectedIndex = 1;
        }

        /// <summary>
        /// methos to load our serial
        /// port option values
        /// </summary>
        private void LoadValues()
        {
            List<string> sAvailablePorts = ecmCommMan.FindAvailablePorts();
            List<string> sParityValues = ecmCommMan.GetParityValues();
            List<string> sStopBitValues = ecmCommMan.GetStopBitValues();
            cboPort.Items.AddRange(sAvailablePorts.ToArray());
            cboParity.Items.AddRange(sParityValues.ToArray());
            cboStop.Items.AddRange(sStopBitValues.ToArray());

        }

        /// <summary>
        /// method to set the state of controls
        /// when the form first loads
        /// </summary>
        private void SetControlState()
        {
            rbText.Checked = true;
            rbFrontCoil.Checked = true;
            rbVersionNo.Checked = true;
            btnCmdSend.Enabled = false;
            btnCmdClose.Enabled = false;
        }

        #region DisplayData
        /// <summary>
        /// method to display the data to & from the port
        /// on the screen
        /// </summary>
        /// <param name="type">MessageType of the message</param>
        /// <param name="msg">Message to display</param>
        [STAThread]
        public void DisplayData(ECMCommMan.MessageType type, string msg)
        {
            rtbDisplay.Invoke(new EventHandler(delegate
            {
                rtbDisplay.SelectedText = string.Empty;
                rtbDisplay.SelectionFont = new Font(rtbDisplay.SelectionFont, FontStyle.Bold);
                rtbDisplay.SelectionColor = MessageColor[(int)type];
                rtbDisplay.AppendText(msg);
                rtbDisplay.ScrollToCaret();
            }
                ));
        }
        #endregion

        private void cmdSend_Click(object sender, EventArgs e)
        {
            ecmCommMan.WriteData(txtSend.Text);
        }

        private void rdoText_CheckedChanged(object sender, EventArgs e)
        {
            if (rbText.Checked == true)
            {
                ecmCommMan.CurrentTransmissionType = ECMCommunicationManager.TransmissionType.Text;
                gbGauges.Visible = true;
            }
        }

        private void rdoHex_CheckedChanged(object sender, EventArgs e)
        {
            if (rbHex.Checked == true)
            {
                ecmCommMan.CurrentTransmissionType = ECMCommunicationManager.TransmissionType.Hex;
                gbGauges.Visible = true;
            }
        }

        private void rdoDash_CheckedChanged(object sender, EventArgs e)
        {
            if (rbDash.Checked == true)
            {
                ecmCommMan.CurrentTransmissionType = ECMCommunicationManager.TransmissionType.DASH;
                gbDashRequest.Visible = true;
                gbGauges.Visible = false;
            }
        }

        private void rdoECM_CheckedChanged(object sender, EventArgs e)
        {
            if (rbECM.Checked == true)
            {
                ecmCommMan.CurrentTransmissionType = ECMCommunicationManager.TransmissionType.ECM;
                gbDashRequest.Visible = false;
                gbGauges.Visible = true;
            }
        }

        private void cmdClose_Click(object sender, EventArgs e)
        {
            ecmCommMan.ClosePort();

            btnCmdOpen.Enabled = true;
            btnCmdClose.Enabled = false;
            btnCmdSend.Enabled = false;
        }

        private void btnSaveCSV_Click(object sender, EventArgs e)
        {
            using (CsvFileWriter writer = new CsvFileWriter("C:\\WriteTest.csv"))
            {
                CsvRow headerRow = new CsvRow();
                foreach (DataGridViewColumn dgColumn in dgRunTimeData.Columns)
                {
                    headerRow.Add(dgColumn.Name);
                }
                writer.WriteRow(headerRow);

                foreach (DataGridViewRow dgRow in dgRunTimeData.Rows)
                {
                    CsvRow row = new CsvRow();

                    foreach (DataGridViewCell cell in dgRow.Cells)
                    {
                        string str = (string)cell.FormattedValue;
                        row.Add(str);
                    }
                    writer.WriteRow(row);
                }

            }
        }

        private void btnReadCSV_Click(object sender, EventArgs e)
        {
            // Get the CSV file from the dialog box
            openFD.Title = "Choose CSV file for import";
            openFD.ShowDialog();
            string sCSVPath = openFD.FileName;

            using (CsvFileReader reader = new CsvFileReader(sCSVPath))
            {
                DataTable RunTimeDataTable = new DataTable();
                CsvRow row = new CsvRow();

                //read the first line and set as header
                reader.ReadRow(row);
                foreach(string sHeader in row)
                {
                    RunTimeDataTable.Columns.Add(sHeader);
                }

                //read the rest and build the row
                while (reader.ReadRow(row))
                {
                    //object[] array = new object[row.Count];
                    //for (int i = 0; i < row.Count; i++)
                    //{
                    //    array[i] = row[i];
                    //}
                    RunTimeDataTable.Rows.Add(row.ToArray());
                }
                dgRunTimeData.DataSource = RunTimeDataTable;
                dgRunTimeData.AutoResizeColumns();
                dgRunTimeData.RowHeadersVisible = false;
                //DataGridView dg = (DataGridView)this.GetType().GetField("dgRunTimeData", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this);
                dgRunTimeData.Columns["Type"].Visible = false;
                dgRunTimeData.Columns["Export"].Visible = false;

                btnECMSimulation.Enabled = true;

                //int ncount = dg.RowCount;

                //for (int counter = 0; counter < ncount; counter++)
                //{
                //    dg.Rows[counter].Visible = false;
                //}
            }
        }        

        #region Column to string conversion
        /// <summary>
        /// method to convert a column from a DataGridView into a string
        /// <param> sColumnName="name"></param>
        /// <returns> a string containing all runtime data</returns>
        public string ColumntoString(string sDataGridName, string sColumnName)
        {
            string sHexData = "";
            //int bHexData = 0;
            //int bNumber = 0;

            //DataGridView dg = (DataGridView)this.GetType().GetField(sDataGridName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this);

            for (int i = 0; i < dgRunTimeData.Rows.Count; i++)
            {
                sHexData = sHexData + dgRunTimeData.Rows[i].Cells[sColumnName].Value.ToString();
                //byte[] newMsg = ecmCommMan.HexToByte(sHexData); 
            }
            return sHexData;
        }
        #endregion

        #region Write data to Runtime Table
        /// <summary>
        /// method to extract a cell value from the data grid
        /// <param> sDataGridName="name", sColumnName="name", sRowNameSearch="name"</param>
        /// <returns> a 16 bit hex value</returns>
        //public string WriteHexValueToTable(string sDataGridName, string sColumnName, string sRowNameSearch, int value)
        public bool WriteHexValueToTable(string sColumn, int nRow, int nValue)
        {
            //DataGridView dg = (DataGridView)this.GetType().GetField(sDataGridName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this);

            if ((string)dgRunTimeData["Size (bytes)", nRow].Value == "2")
            {
                dgRunTimeData[sColumn, nRow].Value = nValue.ToString("X4");
            }
            else
            {
                dgRunTimeData[sColumn, nRow].Value = nValue.ToString("X2");
            }
            return true;
        }
        #endregion

        public void ChangeVersionNo(string sVersionNo)
        {
            tbSetVersionNo.Text = sVersionNo;
        }

        public string ReadVersionNo()
        {
            return tbSetVersionNo.Text;
        }

        private void btnHideUnhide_Click(object sender, EventArgs e)
        {
            dgRunTimeData.Rows[1].Visible = false;
        }

        private void bRequestLiveData_Click(object sender, EventArgs e)
        {
            if (btnRequestLiveData.Text == "Request")
            {
                if (rbVersionNo.Checked == true)
                {
                    ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMVersion);
                }
                if (rbLiveData.Checked == true)
                {
                    ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMRunTimeData);
                    btnRequestLiveData.Text = "Stop";
                    timer1.Enabled = true;
                }
            }
            else
            {
                btnRequestLiveData.Text = "Request";
                timer1.Enabled = false;
            }
        }

        private void bRequestDiagnostics_Click(object sender, EventArgs e)
        {
            if (rbFrontCoil.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.FrontCoil);
            }
            if (rbRearCoil.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.RearCoil);
            }
            if (rbTachometer.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.Tachometer);
            }
            if (rbFuelPump.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.FuelPump);
            }
            if (rbFrontInjector.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.FrontInj);
            }
            if (rbRearInjector.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.RearInj);
            }
            if (rbFan.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.Fan);
            }
            if (rbExhaustValve.Checked == true)
            {
                ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.ExhaustValve);
            }
        }

        private void bTPSReset_Click(object sender, EventArgs e)
        {
            ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.TPSReset);
        }

        private void bClearErrorCodes_Click(object sender, EventArgs e)
        {
            ecmCommMan.ECMDataRequest((byte)ECMCommunicationManager.ECMCommandType.ECMSet, 0x00, 0x20, (byte)ECMCommunicationManager.ECMVirtualPageFunction.ClearCodes);
        }

        private void bECMSimulation_Click(object sender, EventArgs e)
        {
            if (btnECMSimulation.Text == "Start")
            {
                timer1.Enabled = true;
                btnECMSimulation.Text = "Stop";
            }
            else
            {
                timer1.Enabled = false;
                btnECMSimulation.Text = "Start";
             }
        }
    }
}
